home *** CD-ROM | disk | FTP | other *** search
/ PC World Komputer 2010 April / PCWorld0410.iso / pluginy Firefox / 1122 / 1122.xpi / chrome / tabmixplus.jar / content / tabmixplus / minit / minit.js < prev    next >
Text File  |  2009-09-27  |  36KB  |  940 lines

  1. //code from Dorando and Sboulema's MiniT+, modified by Hemiola SUN
  2. // modified by onemen
  3.  
  4. const DRAG_LINK = 0;
  5. const DRAG_TAB_TO_NEW_WINDOW = 1;
  6. const DRAG_TAB_IN_SAME_WINDOW = 2;
  7.  
  8. function TMP_DragAndDrop_init() {
  9.   TMP_setDragEvents(true);
  10.  
  11.   if (!gIsFirefox35) {
  12.     // for Firefox Dragmark
  13.     gBrowser.mTabDropIndicatorBar.addEventListener('dragover', TMP_TabDragOver, true);
  14.     gBrowser.mTabDropIndicatorBar.addEventListener('dragdrop', TMP_TabDragDrop, true);
  15.   }
  16.  
  17.   // insert vide-bar after update mTabDropIndicatorBar to prevent bug 398254
  18.   // Bug 398254 û Since the landing of 372769, I can no longer drag and drop tabs with TabMixPlus
  19.   gBrowser.mTabBox.insertBefore(document.getElementById('vide-bar'), gBrowser.mTabBox.firstChild);
  20.  
  21.   var stringBundle = document.getElementById("tmp-string-bundle");
  22.   TabDNDObserver.draglink = stringBundle.getString("droplink.label")
  23. }
  24.  
  25. function TMP_setDragEvents(atStart) {
  26.   // we only set Tabmix events at start if Tree Style Tab is not in vertical mode
  27.   var useDefaultDnD = false;
  28.   if ("TreeStyleTabBrowser" in window) {
  29.     try {
  30.       var tabbarPosition = gTabmixPrefs.getCharPref("extensions.treestyletab.tabbar.position").toLowerCase();
  31.     }
  32.     catch (er) {};
  33.     useDefaultDnD = tabbarPosition == "left" || tabbarPosition == "right";
  34.   }
  35.  
  36.   if (atStart && useDefaultDnD) {
  37.     gBrowser.mStrip.useDefaultDnD = useDefaultDnD;
  38.     return; // nothing to do here;
  39.   }
  40.  
  41.   if ("useDefaultDnD" in gBrowser.mStrip && gBrowser.mStrip.useDefaultDnD == useDefaultDnD) {
  42.     return; // nothing to do here;
  43.   }
  44.   gBrowser.mStrip.useDefaultDnD = useDefaultDnD;
  45.  
  46.   if (useDefaultDnD && gIsFirefox35) {
  47.     gBrowser.mStrip.setAttribute("ondragstart", "this.parentNode.parentNode._onDragStart(event);");
  48.     gBrowser.mStrip.setAttribute("ondragover", "this.parentNode.parentNode._onDragOver(event);");
  49.     gBrowser.mStrip.setAttribute("ondrop", "this.parentNode.parentNode._onDrop(event);");
  50.     gBrowser.mStrip.setAttribute("ondragend", "this.parentNode.parentNode._onDragEnd(event);");
  51.     gBrowser.mStrip.setAttribute("ondragleave", "this.parentNode.parentNode._onDragLeave(event);");
  52.     gBrowser.mTabDropIndicatorBar.setAttribute("ondragover", "this.parentNode.parentNode._onDragOver(event);");
  53.     gBrowser.mTabDropIndicatorBar.setAttribute("ondragleave", "this.parentNode.parentNode._onDragLeave(event);");
  54.     gBrowser.mTabDropIndicatorBar.setAttribute("ondrop", "this.parentNode.parentNode._onDrop(event);");
  55.   }
  56.   else if (useDefaultDnD && !gIsFirefox35) {
  57.     gBrowser.mStrip.setAttribute("ondraggesture","nsDragAndDrop.startDrag(event, this.parentNode.parentNode); event.stopPropagation();");
  58.     gBrowser.mStrip.setAttribute("ondragover","nsDragAndDrop.dragOver(event, this.parentNode.parentNode); event.stopPropagation();");
  59.     gBrowser.mStrip.setAttribute("ondragdrop","nsDragAndDrop.drop(event, this.parentNode.parentNode); event.stopPropagation();");
  60.     gBrowser.mStrip.setAttribute("ondragexit","nsDragAndDrop.dragExit(event, this.parentNode.parentNode); event.stopPropagation();");
  61.   }
  62.   else if (gIsFirefox35) {
  63.     gBrowser.mStrip.setAttribute("ondragstart", "TabDNDObserver.onDragStart(event)");
  64.     gBrowser.mStrip.setAttribute("ondragover", "TabDNDObserver.onDragOver(event)");
  65.     gBrowser.mStrip.setAttribute("ondrop", "TabDNDObserver.onDrop(event);");
  66.     gBrowser.mStrip.setAttribute("ondragend", "TabDNDObserver.onDragEnd(event);");
  67.     gBrowser.mStrip.setAttribute("ondragleave", "TabDNDObserver.onDragExit(event);");
  68.     gBrowser.mTabDropIndicatorBar.setAttribute("ondragover", "TabDNDObserver.onDragOver(event);");
  69.     gBrowser.mTabDropIndicatorBar.setAttribute("ondragleave", "TabDNDObserver.onDragExit(event);");
  70.     gBrowser.mTabDropIndicatorBar.setAttribute("ondrop", "TabDNDObserver.onDrop(event);");
  71.   }
  72.   else {
  73.     gBrowser.mStrip.setAttribute("ondraggesture", "TMP_TabDragGesture(event);");
  74.     gBrowser.mStrip.setAttribute("ondragover", "TMP_TabDragOver(event);");
  75.     gBrowser.mStrip.setAttribute("ondragdrop", "TMP_TabDragDrop(event);");
  76.     gBrowser.mStrip.setAttribute("ondragexit", "TMP_TabDragExit(event);");
  77.   }
  78. }
  79.  
  80. ///////////////////////////////////////////////////////////////////////////
  81. //// Drag and Drop observers
  82.  
  83. function TMP_TabDragGesture(aEvent) {
  84.    nsDragAndDrop.startDrag(aEvent, TabDNDObserver);
  85.    aEvent.stopPropagation();
  86. }
  87.  
  88. function TMP_TabDragOver(aEvent) {
  89.    nsDragAndDrop.dragOver(aEvent, TabDNDObserver);
  90.    aEvent.stopPropagation();
  91. }
  92.  
  93. function TMP_TabDragDrop(aEvent) {
  94.    nsDragAndDrop.drop(aEvent, TabDNDObserver);
  95.    aEvent.stopPropagation();
  96. }
  97.  
  98. function TMP_TabDragExit(aEvent) {
  99.    nsDragAndDrop.dragExit(aEvent, TabDNDObserver);
  100. }
  101.  
  102. var TabDNDObserver = {
  103.   gBackupLabel: "",
  104.   gMsg: null,
  105.   draglink: "",
  106.   lastTime: 0,
  107.   dragmarkindex: null,
  108.   marginBottom: 0,
  109.  
  110.   onDragStart: function (event, transferData, action) {
  111.     if (gIsFirefox35)
  112.       this._dragLeftWindow = false;
  113.     if (event.target.localName != "tab" || event.originalTarget.localName == "toolbarbutton")
  114.       return;
  115.  
  116.     for ( var i = 0; i < gBrowser.mTabs.length; i++ )
  117.       gBrowser.mTabs[i].setAttribute("showbutton","off");
  118.  
  119.     var draggedTab = event.target;
  120.     var uri = gBrowser.getBrowserForTab(draggedTab).currentURI;
  121.     var spec = uri ? uri.spec : "about:blank";
  122.  
  123.     if (gIsFirefox35) {
  124.       var dt = event.dataTransfer;
  125.       dt.mozSetDataAt(TAB_DROP_TYPE, draggedTab, 0);
  126.       // We must not set text/x-moz-url or text/plain data here,
  127.       // otherwise trying to deatch the tab by dropping it on the desktop
  128.       // may result in an "internet shortcut"
  129.       dt.mozSetDataAt("text/x-moz-text-internal", spec, 0);
  130.       // Set the cursor to an arrow during tab drags.
  131.       dt.mozCursor = "default";
  132.  
  133.       var canvas = tabPreviews.capture(draggedTab, false);
  134.       dt.setDragImage(canvas, 0, 0);
  135.       event.stopPropagation();
  136.     }
  137.     else { // Firefox 3.0.X
  138.       var label = uri ? draggedTab.label : gBrowser.mStringBundle.getString("tabs.untitled");
  139.       transferData.data = new TransferData();
  140.       transferData.data.addDataForFlavour("text/x-moz-url", spec + "\n" + label);
  141.       transferData.data.addDataForFlavour("text/unicode", spec);
  142.       transferData.data.addDataForFlavour("text/html", '<a href="' + spec + '">' + label + '</a>');
  143.     }
  144.  
  145.   },
  146.  
  147.   onDragOver: function minit_onDragOver(event, flavours, session) {
  148.     var dt = event.dataTransfer;
  149.  
  150.     var sourceNode = TMP_getSourceNode(dt, session);
  151.     var draggeType = this.getDragType(sourceNode);
  152.     var newIndex = this.getNewIndex(event);
  153.     var oldIndex = draggeType != DRAG_LINK ? sourceNode._tPos : -1;
  154.     var left_right; // 1:right, 0: left, -1: drop link on tab to replace tab
  155.     if (newIndex < gBrowser.mTabs.length)
  156.       left_right = this.getLeft_Right(event, newIndex, oldIndex, draggeType);
  157.     else {
  158.       newIndex = draggeType != DRAG_TAB_IN_SAME_WINDOW && tabxPrefs.getBoolPref("openTabNext") ? gBrowser.mTabContainer.selectedIndex :
  159.                   gBrowser.mTabs.length - 1;
  160.       left_right = 1;
  161.     }
  162.  
  163.     var isCopy;
  164.     if (gIsFirefox35) {
  165.       isCopy = dt.dropEffect == "copy";
  166.       var effects = this._setEffectAllowedForDataTransfer(event, draggeType);
  167.     }
  168.     else
  169.       isCopy = (event.ctrlKey || event.metaKey);
  170.  
  171.     var replaceTab = (left_right == -1);
  172.     /* we don't allow to drop link on lock tab.
  173.      * unless:
  174.      *           - the tab is blank
  175.      *     or    - the user press Ctrl/Meta Key
  176.      *     or    - we drop link that start download
  177.      */
  178.     if (replaceTab && !isCopy) {
  179.       var targetTab = gBrowser.mTabs[newIndex];
  180.       if (targetTab.getAttribute("locked") && !gBrowser.isBlankNotBusyTab(targetTab)) {
  181.         try {
  182.           var url;
  183.           if (gIsFirefox35)
  184.             url = this.retrieveURLFromData(dt);
  185.           else {
  186.             var dropData = nsTransferable.get(new FlavourSet([flavours]), nsDragAndDrop.getDragData, true).first.first;
  187.             url = transferUtils.retrieveURLFromData(dropData.data, dropData.flavour.contentType);
  188.           }
  189.           if (!url || !url.length || url.indexOf(" ", 0) != -1 ||
  190.               /^\s*(javascript|data):/.test(url))
  191.             url = null;
  192.  
  193.           var disAllowDrop = url ? !isUrlForDownload(url) : true;
  194.         } catch (ex) { TMP_ASSERT(ex);}
  195.  
  196.         if (disAllowDrop)
  197.           gIsFirefox35 ? dt.effectAllowed = "none" : session.canDrop = false;
  198.       }
  199.     }
  200.  
  201.     var canDrop;
  202.     var hideIndicator = false;
  203.     if (gIsFirefox35) {
  204.       if (effects == "") {
  205.         this.clearDragmark();
  206.         return;
  207.       }
  208.       canDrop = effects != "none";
  209.       if (canDrop && !isCopy && draggeType == DRAG_TAB_IN_SAME_WINDOW && oldIndex == newIndex) {
  210.         canDrop = false;
  211.         dt.effectAllowed = "none";
  212.       }
  213.  
  214.       event.preventDefault();
  215.       event.stopPropagation();
  216.     }
  217.     else {
  218.       if (draggeType == DRAG_TAB_IN_SAME_WINDOW && oldIndex == newIndex)
  219.         session.canDrop = isCopy && event.target != sourceNode;
  220.  
  221.       canDrop = session.canDrop;
  222.       if (canDrop && !this.isValidTarget(event, session))
  223.         return;
  224.     }
  225.  
  226.     // show Drag & Drop message
  227.     if (draggeType == DRAG_LINK) {
  228.       this.gMsg = event.originalTarget.getAttribute("command") == "cmd_newNavigatorTab" ?
  229.                               gNavigatorBundle.getString("droponnewtabbutton") : this.draglink;
  230.       if (event.target.localName != "tab" && event.target.localName != "tabs")
  231.         this.gMsg = this.gBackupLabel;
  232.       var statusTextFld = document.getElementById("statusbar-display");
  233.       if (statusTextFld.label != this.gMsg) {
  234.         if (this.gBackupLabel == "")
  235.           this.gBackupLabel = statusTextFld.label;
  236.         statusTextFld.label = this.gMsg;
  237.       }
  238.     }
  239.  
  240.     var tabBar = gBrowser.mTabContainer;
  241.     if (tabBar.canScrollTabsLeft || tabBar.canScrollTabsRight) {
  242.       var _scroll, targetAnonid;
  243.       if (tabscroll > 0) // scroll with button
  244.         targetAnonid = event.originalTarget.getAttribute("anonid");
  245.       // scroll without button
  246.       else if (event.clientX <= tabBar.tabstrip.boxObject.x)
  247.         targetAnonid = "scrollbutton-up";
  248.       else if(event.clientX >= (tabBar.tabstrip.boxObject.x + tabBar.tabstrip.boxObject.width))
  249.         targetAnonid = "scrollbutton-down";
  250.  
  251.       switch (targetAnonid) {
  252.         case "scrollbutton-up":
  253.           if (tabBar.canScrollTabsLeft)
  254.             _scroll = -1;
  255.             break;
  256.         case "scrollbutton-down":
  257.           if (tabBar.canScrollTabsRight)
  258.             _scroll = 1;
  259.             break;
  260.       }
  261.       if (_scroll) {
  262.         var newTime = new Date().getTime();
  263.         if (newTime - this.lastTime > 100) {
  264.           gBrowser.mTabContainer.tabsScroll(_scroll);
  265.           this.lastTime = newTime;
  266.         }
  267.         hideIndicator = true;
  268.       }
  269.     }
  270.  
  271.     // start fix from bug 248612
  272.     if (draggeType == DRAG_LINK && event.target.localName == "tab") {
  273.       if (!gBrowser.mDragTime)
  274.         gBrowser.mDragTime = Date.now();
  275.       if (Date.now() >= gBrowser.mDragTime + gBrowser.mDragOverDelay)
  276.         gBrowser.mTabContainer.selectedItem = event.target;
  277.     }
  278.     // end fix from bug 248612
  279.  
  280.     if ( replaceTab || hideIndicator || !canDrop) {
  281.       this.clearDragmark();
  282.       return;
  283.    }
  284.  
  285.    this.setDragmark(newIndex, left_right);
  286.   },
  287.  
  288.   onDrop: function minit_onDrop(event, dropData, session) {
  289.     this.clearDragmark();
  290.     var dt = event.dataTransfer;
  291.     var sourceNode = TMP_getSourceNode(dt, session);
  292.     var draggeType = this.getDragType(sourceNode);
  293.     var isCopy = gIsFirefox35 ? (dt.dropEffect == "copy") : (event.ctrlKey || event.metaKey);
  294.     var draggedTab;
  295.     if (draggeType != DRAG_LINK) {
  296.       draggedTab = sourceNode;
  297.       // not our drop then
  298.       if (!draggedTab)
  299.         return;
  300.     }
  301.  
  302.     if (gIsFirefox35) {
  303.       event.stopPropagation();
  304.     }
  305.  
  306.     var isTabReorder = draggeType == DRAG_TAB_IN_SAME_WINDOW // TreeStyleTab extension look for isTabReorder in our code
  307.     var newIndex = this.getNewIndex(event);
  308.     var oldIndex = draggedTab ? draggedTab._tPos : -1;
  309.     var left_right;
  310.  
  311.     if (newIndex < gBrowser.mTabs.length)
  312.        left_right = this.getLeft_Right(event, newIndex, oldIndex, draggeType);
  313.     else {
  314.        newIndex = draggeType != DRAG_TAB_IN_SAME_WINDOW && tabxPrefs.getBoolPref("openTabNext") ? gBrowser.mTabContainer.selectedIndex :
  315.                    gBrowser.mTabs.length - 1;
  316.        left_right = 1;
  317.     }
  318.  
  319.     if (draggedTab && (isCopy || draggeType == DRAG_TAB_IN_SAME_WINDOW)) {
  320.       if (isCopy) {
  321.         // copy the dropped tab (wherever it's from)
  322.         var newTab = gBrowser.duplicateTab(draggedTab);
  323.         gBrowser.moveTabTo(newTab, newIndex + left_right);
  324.  
  325.         if (draggeType == DRAG_TAB_TO_NEW_WINDOW || event.shiftKey)
  326.           gBrowser.selectedTab = newTab;
  327.       }
  328.       else {
  329.         // move the dropped tab
  330.         newIndex += left_right - (newIndex > oldIndex);
  331.         if (newIndex != draggedTab._tPos)
  332.           gBrowser.moveTabTo(draggedTab, newIndex);
  333.       }
  334.  
  335.       draggedTab.collapsed = false;
  336.       // probably there is no way to drag collapsed tab....
  337.       var firstVisibleIndex = gBrowser.mTabContainer.collapsedTabs;
  338.       if ( gBrowser.mTabContainer.getAttribute("flowing") == "multibar" &&
  339.             gBrowser.mTabContainer.getAttribute("multibar") == "scrollbar" &&
  340.             oldIndex < firstVisibleIndex )
  341.         gBrowser.mTabs[firstVisibleIndex - 1].collapsed = true;
  342.       gBrowser.mTabContainer.ensureTabIsVisible(newIndex);
  343.       checkBeforeAndAfter();
  344.     }
  345.     else if (draggedTab) {
  346.       if (gIsFirefox35) { // Firefox 3.5+
  347.         // swap the dropped tab with a new one we create and then close
  348.         // it in the other window (making it seem to have moved between
  349.         // windows)
  350.         newTab = gBrowser.addTab("about:blank");
  351.         var newBrowser = gBrowser.getBrowserForTab(newTab);
  352.         // Stop the about:blank load
  353.         newBrowser.stop();
  354.         // make sure it has a docshell
  355.         newBrowser.docShell;
  356.  
  357.         gBrowser.moveTabTo(newTab, newIndex + left_right);
  358.  
  359.         gBrowser.swapBrowsersAndCloseOther(newTab, draggedTab);
  360.  
  361.         // We need to set selectedTab after we've done
  362.         // swapBrowsersAndCloseOther, so that the updateCurrentBrowser
  363.         // it triggers will correctly update our URL bar.
  364.         gBrowser.selectedTab = newTab;
  365.       }
  366.       else {
  367.         // Firefox 3.0
  368.         // copy the dropped tab and remove it from the other window
  369.         // (making it seem to have moved between windows)
  370.         var sourceWindow = draggedTab.ownerDocument.defaultView;
  371.         var remoteBrowser = sourceWindow.gBrowser;
  372.         var tabCount = remoteBrowser.tabContainer.childNodes.length;
  373.         newTab = gBrowser.duplicateTab(draggedTab);
  374.         gBrowser.moveTabTo(newTab, newIndex + left_right);
  375.         gBrowser.selectedTab = newTab;
  376.         remoteBrowser.removeTab(draggedTab);
  377.         // close the other window if gBrowser was its last tab
  378.         if (tabCount == 1)
  379.           draggedTab.ownerDocument.defaultView.close();
  380.       }
  381.     }
  382.     else {
  383.       var url;
  384.       if (gIsFirefox35)
  385.         url = this.retrieveURLFromData(dt);
  386.       else
  387.         url = transferUtils.retrieveURLFromData(dropData.data, dropData.flavour.contentType);
  388.  
  389.       // valid urls don't contain spaces ' '; if we have a space it isn't a valid url.
  390.       // Also disallow dropping javascript: or data: urls--bail out
  391.       if (!url || !url.length || url.indexOf(" ", 0) != -1 ||
  392.          /^\s*(javascript|data):/.test(url))
  393.          return;
  394.  
  395.       if (gIsFirefox35) {
  396.         var dragService = Cc["@mozilla.org/widget/dragservice;1"].getService(Ci.nsIDragService);
  397.         session = dragService.getCurrentSession();
  398.       }
  399.       nsDragAndDrop.dragDropSecurityCheck(event, session, url);
  400.       var bgLoad = true;
  401.       try {
  402.         bgLoad = gBrowser.mPrefs.getBoolPref("browser.tabs.loadInBackground");
  403.       }
  404.       catch (e) { }
  405.  
  406.       if (event.shiftKey)
  407.         bgLoad = !bgLoad; // shift Key reverse the pref
  408.  
  409.       url = getShortcutOrURI(url);
  410.       var tab = null;
  411.       if (left_right > -1 && !isUrlForDownload(url)) {
  412.         // We're adding a new tab.
  413.          try {
  414.             tab = gBrowser.addTab(url);
  415.             gBrowser.moveTabTo(tab, newIndex + left_right);
  416.          } catch(ex) {
  417.             // Just ignore invalid urls
  418.             tmLog("addTab\n" + ex);
  419.             return;
  420.          }
  421.       }
  422.       else {
  423.         // Load in an existing tab.
  424.         tab = event.target.localName == "tab" ? event.target : gBrowser.mTabs[newIndex];
  425.         try {
  426.           gBrowser.getBrowserForTab(tab).loadURI(url);
  427.         } catch(ex) {
  428.           // Just ignore invalid urls
  429.           tmLog("load\n" + ex);
  430.           return;
  431.         }
  432.       }
  433.       if (gBrowser.mCurrentTab != tab)
  434.         gBrowser.TMP_selectNewForegroundTab(tab, bgLoad, url);
  435.     }
  436.   },
  437.  
  438.   onDragEnd: function minit_onDragEnd(aEvent) {
  439.     // see comment in gBrowser._onDragEnd
  440.     // don't allow to open new window in single window mode
  441.     var dt = aEvent.dataTransfer;
  442.     if (gSingleWindowMode || dt.mozUserCancelled || dt.dropEffect != "none")
  443.       return;
  444.     this.clearDragmark(aEvent);
  445.     // Disable detach within the browser toolbox
  446.     var eX = aEvent.screenX;
  447.     var wX = window.screenX;
  448.     // check if the drop point is horizontally within the window
  449.     if (eX > wX && eX < (wX + window.outerWidth)) {
  450.       // also avoid detaching if the the tab was dropped too close to
  451.       // the tabbar (half a tab)
  452.       var tabBar = gBrowser.mTabContainer;
  453.       var bo = tabBar.mTabstrip.boxObject;
  454.       var tabHeight = tabBar.childNodes[tabBar.collapsedTabs].boxObject.height;
  455.       var endScreenY = bo.screenY + bo.height + 0.5 * tabHeight;
  456.       var eY = aEvent.screenY;
  457.       if (gTabbarPosition == 0) {// tabbar on the top
  458.         if (eY < endScreenY && eY > window.screenY)
  459.           return;
  460.       }
  461.       else {// bottom
  462.         var tb = gNavToolbox.boxObject;
  463.         var toolboxEndScreenY = tb.screenY + tb.height;
  464.         var startScreenY = bo.screenY - 0.5 * tabHeight;
  465.         if ((eY > startScreenY && eY < endScreenY) || eY < toolboxEndScreenY)
  466.           return;
  467.       }
  468.  
  469.     }
  470.  
  471.     var draggedTab = dt.mozGetDataAt(TAB_DROP_TYPE, 0);
  472.     gBrowser.replaceTabWithWindow(draggedTab);
  473.     aEvent.stopPropagation();
  474.   },
  475.  
  476.   onDragExit: function minit_onDragExit(event, session) {
  477.     event.stopPropagation();
  478.     gBrowser.mDragTime = 0;
  479.  
  480.     if (gIsFirefox35) {
  481.       var target = event.relatedTarget;
  482.       while (target && target.localName != "tabs")
  483.         target = target.parentNode;
  484.       if (target)
  485.         return;
  486.  
  487.       this.clearDragmark();
  488.     }
  489.     else
  490.       this.isValidTarget(event, session);
  491.   },
  492.  
  493.   isValidTarget: function minit_isValidTarget(event, session) {
  494.     var tabStripBoxObject = gBrowser.mStrip.boxObject;
  495.     if ( event.clientY <= tabStripBoxObject.y + 1 ||
  496.          event.clientX < tabStripBoxObject.x ||
  497.          event.clientY >= tabStripBoxObject.y + tabStripBoxObject.height) {
  498.       var statusTextFld = document.getElementById("statusbar-display");
  499.       if (statusTextFld.label == this.gMsg) {
  500.         statusTextFld.label = this.gBackupLabel;
  501.         this.gBackupLabel = "";
  502.       }
  503.       this.clearDragmark();
  504.       gIsFirefox35 ? event.dataTransfer.effectAllowed = "none" : session.canDrop = false;
  505.       return false;
  506.     }
  507.     return true;
  508.   },
  509.  
  510.   getNewIndex: function (event) {
  511.     // start to chack after collapsedTabs
  512.     // if X is less then the first tab return 0
  513.     // check if the tab is visible... if not return gBrowser.mTabs.length
  514.     // check if Y is below the tab.... if yes go to next row
  515.     // in the row find the closest tab by X,
  516.     // if no tab is match return gBrowser.mTabs.length
  517.     var mX = event.clientX, mY = event.clientY;
  518.     var i, tabBar = gBrowser.mTabContainer;
  519.     var tabs = tabBar.childNodes;
  520.     var collapsed = tabBar.collapsedTabs;
  521.     if (!tabBar.hasAttribute("multibar")) {
  522.       if (window.getComputedStyle(gBrowser, null).direction == "ltr") {
  523.         for (i = event.target.localName == "tab" ? event.target._tPos : collapsed; i < tabs.length; i++)
  524.           if (mX < tabs[i].boxObject.x + tabs[i].boxObject.width)
  525.             return i;
  526.       }
  527.       else {
  528.         for (i = event.target.localName == "tab" ? event.target._tPos : 0 ; i < tabs.length - collapsed; i++)
  529.           if (mX > tabs[i].boxObject.x + tabs[i].boxObject.width*0)
  530.             return i;
  531.       }
  532.     }
  533.     else {
  534.       var j, tab, thisRow;
  535.       var top = tabBar.topTabY;
  536.       if (window.getComputedStyle(gBrowser, null).direction == "ltr") {
  537.         for (i = collapsed; i < tabs.length; i++) {
  538.           if (!tabBar.isTabVisible(i))
  539.             return tabs.length;
  540.           tab = tabs[i];
  541.           thisRow = tabBar.getTabRowNumber(tab, top);
  542.           if (mY >= tab.baseY) {
  543.             while (i < tabs.length - 1 && tabBar.getTabRowNumber(tabs[i+1], top) == thisRow)
  544.               i++;
  545.           }
  546.           else if (mX < tab.boxObject.x + tab.boxObject.width )
  547.             return i;
  548.           else if (i == tabs.length - 1 || tabBar.getTabRowNumber(tabs[i+1], top) != thisRow)
  549.             return i;
  550.         }
  551.       }
  552.       else {
  553.         for (i = collapsed; i < tabs.length; i++) {
  554.           if (!tabBar.isTabVisible(i))
  555.             return tabs.length;
  556.           tab = tabs[i];
  557.           thisRow = tabBar.getTabRowNumber(tab, top);          
  558.           if (mY >= tab.baseY) {
  559.             while (i < tabs.length - 1 && tabBar.getTabRowNumber(tabs[i+1], top) == thisRow)
  560.               i++;
  561.           }
  562.           else if (mX > tab.boxObject.x)
  563.             return i;
  564.           else if (i == tabs.length - 1 || tabBar.getTabRowNumber(tabs[i+1], top) != thisRow)
  565.             return i;
  566.         }
  567.       }
  568.     }
  569.     return tabs.length;
  570.   },
  571.  
  572.   getLeft_Right: function (event, newIndex, oldIndex, draggeType) {
  573.    var clientX = event.clientX;
  574.    var left_right;
  575.    var tab = gBrowser.mTabs[newIndex];
  576.    var tabBo = tab.boxObject;
  577.    var ltr = (window.getComputedStyle(gBrowser, null).direction == "ltr");
  578.    var _left = ltr ? 0 : 1;
  579.    var _right = ltr ? 1 : 0;
  580.  
  581.    var isCtrlKey = ((event.ctrlKey || event.metaKey) && !event.shiftKey && !event.altKey);
  582.    var lockedTab = tab.getAttribute("locked") && !gBrowser.isBlankNotBusyTab(tab);
  583.    if ((draggeType == DRAG_LINK && lockedTab) || (draggeType == DRAG_LINK && !lockedTab && !isCtrlKey)) {
  584.       left_right = (clientX < tabBo.x + tabBo.width / 4 ) ? _left : _right;
  585.       if (left_right == 1 && clientX < tabBo.x + tabBo.width * 3 / 4 )
  586.          left_right = -1;
  587.    }
  588.    else {
  589.       left_right = ( clientX < tabBo.x + tabBo.width / 2 ) ? _left : _right;
  590.       if (!isCtrlKey && draggeType == DRAG_TAB_IN_SAME_WINDOW) {
  591.         if (newIndex == oldIndex - 1)
  592.           left_right = _left;
  593.         else if (newIndex == oldIndex + 1)
  594.           left_right = _right;
  595.       }
  596.    }
  597.  
  598.    return left_right;
  599.   },
  600.  
  601.   getDragType: function minit_getDragType(aSourceNode) {
  602.     if (aSourceNode && aSourceNode instanceof XULElement && aSourceNode.localName == "tab") {
  603.       if (aSourceNode.parentNode == gBrowser.mTabContainer)
  604.         return DRAG_TAB_IN_SAME_WINDOW; // 2
  605.       if (aSourceNode.ownerDocument.defaultView instanceof ChromeWindow &&
  606.            aSourceNode.ownerDocument.documentElement.getAttribute("windowtype") == "navigator:browser")
  607.         return DRAG_TAB_TO_NEW_WINDOW; // 1
  608.     }
  609.     return DRAG_LINK; // 0
  610.   },
  611.  
  612.   setDragmark: function minit_setDragmark(index, left_right) {
  613.     var newIndex = index + left_right;
  614.     if (this.dragmarkindex == newIndex)
  615.       return;
  616.  
  617.    this.clearDragmark();// clear old dragmark if one exist
  618.  
  619.    if (!tabxPrefs.getBoolPref("useFirefoxDragmark")) {
  620.       var sameRow = newIndex != 0 && newIndex != gBrowser.mTabs.length &&
  621.             inSameRow(gBrowser.mTabs[newIndex-1], gBrowser.mTabs[newIndex]);
  622.       if (sameRow || left_right==0)
  623.          this.setDragmarkAttribute(gBrowser.mTabs[newIndex], "atLeft");
  624.       if (sameRow || left_right==1)
  625.          this.setDragmarkAttribute(gBrowser.mTabs[newIndex-1], "atRight");
  626.    }
  627.    else {
  628.       // code for firefox indicator
  629.       var ib = gBrowser.mTabDropIndicatorBar;
  630.       var ind = ib.firstChild;
  631.       this.setFirefoxDropIndicator(true);
  632.       var tabStripBoxObject = gisToolbarMode ? gBrowser.mStrip.boxObject : gBrowser.boxObject;
  633.       var scrollBoxObject = gBrowser.mTabContainer.tabstrip.boxObject;
  634.       var minMargin = scrollBoxObject.x - tabStripBoxObject.x;
  635.       var maxMargin = minMargin + scrollBoxObject.width;
  636.       if (!gisToolbarMode)
  637.          maxMargin = Math.min(maxMargin, ib.boxObject.x + ib.boxObject.width - ind.boxObject.width);
  638.  
  639.       var ltr = (window.getComputedStyle(gBrowser, null).direction == "ltr");
  640.       if (!ltr)
  641.          [minMargin, maxMargin] = [tabStripBoxObject.width - maxMargin, tabStripBoxObject.width - minMargin];
  642.       if (gTabbarPosition != 1)
  643.          this.setFirefoxDropIndicator(false);
  644.       var newMargin;
  645.       var tabBoxObject = gBrowser.mTabs[index].boxObject;
  646.       if (ltr)
  647.          newMargin = tabBoxObject.screenX - tabStripBoxObject.screenX + (left_right == 1 ? tabBoxObject.width : 0);
  648.       else
  649.          newMargin = tabStripBoxObject.screenX - tabBoxObject.screenX + tabStripBoxObject.width - (left_right == 0 ? tabBoxObject.width : 0);
  650.  
  651.       // ensure we never place the drop indicator beyond our limits
  652.       if (newMargin < minMargin)
  653.          newMargin = minMargin;
  654.       else if (newMargin > maxMargin)
  655.             newMargin = maxMargin;
  656.  
  657.       var newMarginY;
  658.       if (gTabbarPosition == 1) {
  659.          newMarginY = tabBoxObject.screenY - (gisToolbarMode ? ind.boxObject.screenY : ib.boxObject.screenY);
  660.       }
  661.       else {
  662.          newMarginY = gBrowser.mTabContainer.boxObject.screenY - tabBoxObject.screenY + this.marginBottom;
  663.       }
  664.  
  665.       if (gisToolbarMode) {
  666.          newMarginY = (gTabbarPosition == 1 ? 1 : -1) * newMarginY + "px";
  667.          ind.style.MozTransform = "translate(" + Math.round(newMargin + ind.boxObject.width / 2) + "px, " + newMarginY + ")";
  668.       }
  669.       else {
  670.          ind.style.MozMarginStart = newMargin + "px";
  671.          if (gTabbarPosition == 1)
  672.             ind.style.marginTop = newMarginY + "px";
  673.          else
  674.             ind.style.marginBottom = newMarginY + "px";
  675.       }
  676.  
  677.       if (gTabbarPosition == 1) {
  678.          ind.style.backgroundPosition = "50% 0%";
  679.       }
  680.       else {
  681.          ind.style.backgroundPosition = "50% 100%";
  682.          this.setFirefoxDropIndicator(true);
  683.       }
  684.     }
  685.  
  686.     this.dragmarkindex = newIndex;
  687.   },
  688.  
  689.   clearDragmark: function minit_clearDragmark() {
  690.     if (this.dragmarkindex == null)
  691.       return;
  692.  
  693.     if (!tabxPrefs.getBoolPref("useFirefoxDragmark")) {
  694.       var index = this.dragmarkindex;
  695.       if (index != gBrowser.mTabs.length && gBrowser.mTabs[index].hasAttribute("dragmark"))
  696.          this.removetDragmarkAttribute(gBrowser.mTabs[index]);
  697.       if (index != 0 && gBrowser.mTabs[index-1].hasAttribute("dragmark"))
  698.          this.removetDragmarkAttribute(gBrowser.mTabs[index-1]);
  699.     }
  700.     else
  701.       this.setFirefoxDropIndicator(false);
  702.  
  703.     this.dragmarkindex = null;
  704.   },
  705.  
  706.   setFirefoxDropIndicator: function (val) {
  707.     var indicator = gisToolbarMode ? gBrowser.mTabDropIndicator : gBrowser.mTabDropIndicatorBar;
  708.     indicator.collapsed = !val;
  709.   },
  710.  
  711.   removetDragmarkAttribute: function (tab) {
  712.     tab.removeAttribute("dragmark");
  713.     tab.maxWidth = gBrowser.mTabContainer.mTabMaxWidth;
  714.     tab.style.maxWidth = tab.maxWidth + "px";
  715.   },
  716.  
  717.   setDragmarkAttribute: function (tab, markSide) {
  718.     tab.maxWidth = tab.boxObject.width;
  719.     tab.style.maxWidth = tab.maxWidth + "px";
  720.     tab.setAttribute("dragmark", markSide);
  721.   },
  722.  
  723.   /*
  724.    *  helper function for firefox 3.0.x
  725.    */
  726.   getSupportedFlavours: function () {
  727.     var flavourSet = new FlavourSet();
  728.     flavourSet.appendFlavour("text/x-moz-url");
  729.     flavourSet.appendFlavour("text/unicode");
  730.     flavourSet.appendFlavour("application/x-moz-file", "nsIFile");
  731.     return flavourSet;
  732.   },
  733.  
  734.   canDrop: function (aEvent, aDragSession) {
  735.     if (aDragSession.sourceNode &&
  736.       aDragSession.sourceNode.parentNode == gBrowser.mTabContainer) {
  737.       var sourceBo = aDragSession.sourceNode.boxObject;
  738.       if (aEvent.screenX >= sourceBo.screenX &&
  739.           aEvent.screenX <= (sourceBo.screenX +sourceBo.width) &&
  740.           aEvent.screenY >= sourceBo.screenY &&
  741.           aEvent.screenY <= (sourceBo.screenY +sourceBo.height))
  742.         return false;
  743.     }
  744.     return true;
  745.   },
  746.  
  747.   /*
  748.    *  helper function for firefox 3.5+
  749.    */
  750.    _detachTab: function minit__detachTab(aEvent, aTab, aSameWindow) {
  751.     // we do here all the work , so always return false
  752.     //
  753.     // Detach only if the mouse pointer was released a little
  754.     // bit down in the content area (to be precise, by tab-height)
  755.     var allowDetach = false;
  756.     // tabbar on top
  757.     if (gTabbarPosition == 0) {
  758.       if (aEvent.screenY > gBrowser.mPanelContainer.boxObject.screenY +
  759.                              aTab.boxObject.height / 2) {
  760.         allowDetach = true;
  761.       }
  762.     }
  763.     // tabbar on bottom
  764.     else if (aEvent.screenY < gBrowser.mStrip.boxObject.screenY -
  765.                              aTab.boxObject.height / 2) {
  766.         allowDetach = true;
  767.     }
  768.     if (!allowDetach)
  769.       return false;
  770.  
  771.     // The dragend event does not contain information about the pressed modifiers
  772.     // XXX check if we can use isCopy = dt.dropEffect == "copy";
  773.     var isCopy = (aEvent.ctrlKey || aEvent.metaKey);
  774.     if (aSameWindow) { // move or copy to new window
  775.       gBrowser.duplicateInWindow(aTab, !isCopy);
  776.     }
  777.     else { // move or copy to this window
  778.       var newTab;
  779.       delete aTab.ownerDocument.defaultView.gBrowser._dragLeftWindow;
  780.       if (isCopy)
  781.         newTab = gBrowser.duplicateTab(aTab);
  782.       else {
  783.         newTab = gBrowser.addTab("about:blank");
  784.         var newBrowser = gBrowser.getBrowserForTab(newTab);
  785.         newBrowser.stop();
  786.         newBrowser.docShell;
  787.         gBrowser.swapBrowsersAndCloseOther(newTab, aTab);
  788.       }
  789.       gBrowser.selectedTab = newTab;
  790.     }
  791.     aEvent.dataTransfer.dropEffect = "move";
  792.     return false;
  793.   },
  794.  
  795.   _setEffectAllowedForDataTransfer: function minit_setEffectAllowed(aEvent, aDraggeType) {
  796.     var dt = aEvent.dataTransfer;
  797.     // Disallow dropping multiple items
  798.     if (dt.mozItemCount > 1)
  799.       return dt.effectAllowed = "none";
  800.  
  801.     var sourceNode = dt.mozGetDataAt(TAB_DROP_TYPE, 0);
  802.     // move or copy tab
  803.     if (aDraggeType != DRAG_LINK) {
  804.       if (aDraggeType == DRAG_TAB_IN_SAME_WINDOW && aEvent.target == sourceNode) {
  805.         return dt.effectAllowed = "none";
  806.       }
  807.       return dt.effectAllowed = "copyMove";
  808.     }
  809.  
  810.     var types = dt.mozTypesAt(0);
  811.     for (var i = 0; i < gBrowser._supportedLinkDropTypes.length; i++) {
  812.       if (types.contains(gBrowser._supportedLinkDropTypes[i])) {
  813.         // Here we need to to do this manually
  814.         return dt.effectAllowed = dt.dropEffect = "link";
  815.       }
  816.     }
  817.     return dt.effectAllowed = "none";
  818.   },
  819.  
  820.   retrieveURLFromData: function minit_retrieveURLFromData(aDataTransfer) {
  821.     for (var i=0; i < gBrowser._supportedLinkDropTypes.length; i++) {
  822.       var dataType = gBrowser._supportedLinkDropTypes[i];
  823.       var isURLList = dataType == "text/uri-list";
  824.       var urlData = isURLList ?
  825.                       aDataTransfer.mozGetDataAt("URL", 0) : aDataTransfer.mozGetDataAt(dataType, 0);
  826.       if (urlData)
  827.         return transferUtils.retrieveURLFromData(urlData, isURLList ? "text/plain" : dataType);
  828.     }
  829.     return null;
  830.   }
  831.  
  832. } // TabDNDObserver end
  833.  
  834. function TMP_goButtonClick(aEvent) {
  835.    if (aEvent.button == 1 && gURLBar.value == gBrowser.currentURI.spec)
  836.       gBrowser.duplicateTab(gBrowser.mCurrentTab);
  837.    else if (aEvent.button != 2) {
  838.       if (gIsFirefox35)
  839.          gURLBar.handleCommand(aEvent);
  840.       else
  841.          handleURLBarCommand(aEvent);
  842.    }
  843. }
  844.  
  845. function TM_BrowserHome() {
  846.    var homePage = gHomeButton.getHomePage();
  847.    if (TMP_whereToOpen(false).inNew) {
  848.       var urls = homePage.split("|");
  849.       var firstTabAdded = gBrowser.addTab(urls[0]);
  850.       var bgLoad = TMP_getBoolPref("browser.tabs.loadBookmarksInBackground", false);
  851.       content.focus();
  852.       gBrowser.TMP_selectNewForegroundTab(firstTabAdded, bgLoad, urls[0]);
  853.  
  854.       for (var i = 1; i < urls.length; ++i)
  855.          gBrowser.addTab(urls[i]);
  856.    }
  857.    else
  858.       loadOneOrMoreURIs(homePage);
  859. }
  860.  
  861. var undocloseTabButtonObserver = {
  862.   onDragOver: function (aEvent, aFlavour, aDragSession) {
  863.     var dt = aEvent.dataTransfer;
  864.     var sourceNode = TMP_getSourceNode(dt, aDragSession);
  865.     if (!sourceNode || sourceNode.localName != "tab") {
  866.       gIsFirefox35 ? dt.effectAllowed = "none" : aDragSession.canDrop = false;
  867.       return true;
  868.     }
  869.  
  870.     var statusTextFld = document.getElementById("statusbar-display");
  871.     var stringBundle = document.getElementById("tmp-string-bundle");
  872.     statusTextFld.label = stringBundle.getString("droptoclose.label");
  873.     aEvent.target.setAttribute("dragover", "true");
  874.     return true;
  875.   },
  876.  
  877.   onDragExit: function (aEvent, aDragSession) {
  878.     if (aEvent.target.hasAttribute("dragover")) {
  879.       var statusTextFld = document.getElementById("statusbar-display");
  880.       statusTextFld.label = "";
  881.       aEvent.target.removeAttribute("dragover");
  882.     }
  883.   },
  884.  
  885.   onDrop: function (aEvent, aXferData, aDragSession) {
  886.     var sourceNode = TMP_getSourceNode(aEvent.dataTransfer, aDragSession);
  887.     if (sourceNode && sourceNode.localName == "tab")
  888.       // let the tabbrowser drag event time to end before we remove the sourceNode
  889.       setTimeout( function (b, aTab) {b.removeTab(aTab, true);}, 0, gBrowser, sourceNode);
  890.   },
  891.  
  892.   getSupportedFlavours: function () {
  893.     var flavourSet = new FlavourSet();
  894.     if (gIsFirefox35)
  895.       flavourSet.appendFlavour(TAB_DROP_TYPE);
  896.     flavourSet.appendFlavour("text/x-moz-url");
  897.     flavourSet.appendFlavour("text/unicode");
  898.     return flavourSet;
  899.   }
  900. }
  901.  
  902. /*
  903.  *  helper function for firefox 3.5+
  904.  */
  905. function TMP_getSourceNode(aDataTransfer, aSession) {
  906.   if (gIsFirefox35) {
  907.     var types = aDataTransfer.mozTypesAt(0);
  908.     if (types[0] == TAB_DROP_TYPE)
  909.       return aDataTransfer.mozGetDataAt(TAB_DROP_TYPE, 0);
  910.     return null;
  911.   }
  912.   return aSession.sourceNode;
  913. }
  914.  
  915. function TMP_whereToOpen(pref, altKey) {
  916.    var aTab = gBrowser.mCurrentTab;
  917.    var isBlankTab = gBrowser.isBlankNotBusyTab(aTab);
  918.    var isLockTab = !isBlankTab && aTab.hasAttribute("locked");
  919.  
  920.    var openTabPref = typeof(pref) == "string" ? gTabmixPrefs.getBoolPref(pref) : pref;
  921.    if (typeof(altKey) != "undefined") {
  922.       // don't reuse balnk tab if the user press alt key when the pref is to open in current tab
  923.       if (altKey && !openTabPref)
  924.          isBlankTab = false;
  925.  
  926.       // see bug 315034 If search is set to open in a new tab,
  927.       // Alt+Enter should open the search result in the current tab
  928.       // so here we reverse the pref if user press Alt key
  929.       openTabPref = (altKey ^ openTabPref) == 1;
  930.    }
  931.    return { inNew: !isBlankTab && (isLockTab || openTabPref), lock: isLockTab };
  932. }
  933.  
  934. function TMP_setStripVisibilityTo(aShow) {
  935.    if (gisToolbarMode)
  936.      gBrowser._toolbar.collapsed = !aShow;
  937.    else
  938.       gBrowser.mStrip.collapsed = !aShow;
  939. }
  940.